package fr.castorhoz.isi_connectivity_widget;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import fr.castorhoz.isi_connectivity_widget.bluetooth_widget.BluetoothBroadcastReceiver;
import fr.castorhoz.isi_connectivity_widget.bluetooth_widget.BluetoothButton;
import fr.castorhoz.isi_connectivity_widget.database.DBAdapter;
import fr.castorhoz.isi_connectivity_widget.gps_widget.GPSBroadcastReceiver;
import fr.castorhoz.isi_connectivity_widget.gps_widget.GPSButton;
import fr.castorhoz.isi_connectivity_widget.mobiledata_widget.MobileDataBroadcastReceiver;
import fr.castorhoz.isi_connectivity_widget.mobiledata_widget.MobileDataButton;
import fr.castorhoz.isi_connectivity_widget.roaming_widget.RoamingButton;
import fr.castorhoz.isi_connectivity_widget.widget_configuration.WidgetConfiguration;
import fr.castorhoz.isi_connectivity_widget.wifi_widget.WifiBroadcastReceiver;
import fr.castorhoz.isi_connectivity_widget.wifi_widget.WifiButton;

/**
 * @author Antoine Merle
 *
 */
public class ConnWidget extends AppWidgetProvider {
	
	private static Map<String, ConnBroadcastReceiver> broadcastReceivers = new HashMap<String, ConnBroadcastReceiver>();
	
	/**
	 * Do not use this list directly. Use getButtonListInstance(Context context) instead
	 */
	private static List<ConnButton> buttonList;
	
	public final static int [] buttonIds = {R.id.button_1, R.id.button_2, R.id.button_3, R.id.button_4, R.id.button_5};

	private static final boolean DEBUG_BROADCAST_RECEIVERS_KEYS = true;

	static {
		Log.e(ConnWidget.class.getName(), "static part of ConnWidget created");
	}
	
	public ConnWidget() {
		Log.d(this.getClass().getName(), "ConnWidget created");
	}
	
	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {

		for (int i = 0; i < appWidgetIds.length; i++) {
			int appWidgetId = appWidgetIds[i];
			updateAppWidget(context, appWidgetManager, appWidgetId);
		}

		super.onUpdate(context, appWidgetManager, appWidgetIds);
	}
	
	private void createBroadcastReceivers(Context context) {

		// //RECEIVERS//////////////////////////////////////////////
		ConnBroadcastReceiver broadcastReceiver = new BluetoothBroadcastReceiver(context);
		broadcastReceivers.put(broadcastReceiver.getBroadcastAction(), broadcastReceiver);
		
		broadcastReceiver = new GPSBroadcastReceiver(context);
		broadcastReceivers.put(broadcastReceiver.getBroadcastAction(), broadcastReceiver);
		
		broadcastReceiver = new MobileDataBroadcastReceiver(context);
		broadcastReceivers.put(broadcastReceiver.getBroadcastAction(), broadcastReceiver);
		
		broadcastReceiver = new WifiBroadcastReceiver(context);
		broadcastReceivers.put(broadcastReceiver.getBroadcastAction(), broadcastReceiver);
		
		if (DEBUG_BROADCAST_RECEIVERS_KEYS) {
			StringBuilder keySet = new StringBuilder();
			keySet.append("keys registered : ");
			for (String key : broadcastReceivers.keySet()) {
				keySet.append(key).append(" ; ");
			}
			Log.d(this.getClass().getName(), keySet.toString());
		}
		////////////////////////////////////////////////////////////
		
	}

	/* (non-Javadoc)
	 * @see android.appwidget.AppWidgetProvider#onEnabled(android.content.Context)
	 */
	@Override
	public void onEnabled(Context context) {		
		Log.i(this.getClass().toString(), "onEnabled called");
		
		Log.d(this.getClass().getName(), "enabling broadcastReceivers");

		//broadcastReceivers.clear();
		createBroadcastReceivers(context);
		
		/*
		 * Ask the user to choose which widget to use
		 * Not satisfying yet, we should stop the apparition of the widget while the activity is up
		 */
		/*Intent intent = new Intent(context, WidgetConfiguration.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		context.startActivity(intent);*/
		
        //buttonList = getButtonListInstance(context, );
		//createBroadcastReceivers(context);
		
		super.onEnabled(context);
	}

	/**
	 * Retrieves user preferences 
	 * @param context
	 * @return
	 */
	private static List<ConnButton> getWidgetsFromPreferences(Context context, int appWidgetId) {
		List<ConnButton> widgets = new ArrayList<ConnButton>();
		SharedPreferences sp = context.getSharedPreferences(WidgetConfiguration.ISI_CONNECTIVITY_WIDGET_PREFERENCES_PREFIX, Context.MODE_PRIVATE);
		String widgetsString = sp.getString(WidgetConfiguration.ISI_CONNECTIVITY_WIDGET_PREFERENCES_PREFIX+appWidgetId, null);
		
		if (widgetsString != null) {
			String[] widgetsNames = widgetsString.split(WidgetConfiguration.SEPARATOR);
			
			for (int position = 0; position < widgetsNames.length; ++position) {
				if (position >= widgets.size()) {
					widgets.add(createWidgetButton(widgetsNames[position], context, appWidgetId));
				} else {
					widgets.add(position, createWidgetButton(widgetsNames[position], context, appWidgetId));
				}
			}
		}
 		return widgets;
	}
	
	/* (non-Javadoc)
	 * @see android.appwidget.AppWidgetProvider#onDeleted(android.content.Context, int[])
	 */
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		super.onDeleted(context, appWidgetIds);
		if (appWidgetIds.length > 0) {
			// TODO delete preferences about those appWidgets

			DBAdapter dbAdapter = new DBAdapter(context);
			dbAdapter.open();
			for (int appWidgetId : appWidgetIds) {
				dbAdapter.removeAppWidgetId(appWidgetId);
			}
			dbAdapter.close();
		}
		
	}

	/**
	 * Get a not null instance of the button list
	 * @param context
	 * @return
	 */
	@SuppressWarnings("unused")
	private static List<ConnButton> getButtonListInstance(Context context, int appWidgetId) {
		if (buttonList == null) {
			buttonList = getWidgetsFromPreferences(context, appWidgetId);
		}
		return buttonList;
	}

	/**
	 * Creates a ConnButton corresponding to the widget name in parameter
	 * @param widgetName
	 * @param context
	 * @return
	 */
	private static ConnButton createWidgetButton(String widgetName, Context context, int appWidgetId) {
		ConnButton button = null;
		switch (ConnButton.widgets.valueOf(widgetName)) {
		case bluetoohWidget:
			button = new BluetoothButton(context);
			break;
		case gpsWidget:
			button = new GPSButton(context);
			break;
		case mobileDataWidget:
			button = new MobileDataButton(context, appWidgetId);
			break;
		case roamingWidget:
			button = new RoamingButton(context);
			break;
		case wifiWidget:
			button = new WifiButton(context, appWidgetId);
			break;
		default:
			break;
		}
		return button;
	}

	
	/**
	 * Creates a ConnBroadcastReceiver corresponding to the action in parameter
	 * @param context
	 * @param action
	 * @return
	 */
	private static ConnBroadcastReceiver createWidgetBroadcastReceiver(Context context, String action) {
		ConnBroadcastReceiver br = null;

		if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {			
			br = new BluetoothBroadcastReceiver(context);
		} else if (action.equals(GPSButton.PROVIDERS_CHANGED_ACTION)) {
			br = new GPSBroadcastReceiver(context);
		} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
			br = new MobileDataBroadcastReceiver(context);
		} else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
			br = new WifiBroadcastReceiver(context);
		}
		return br;
	}

	/**
	 * Update the widget with id appWidgetId.
	 * This method is now public static for the Configuration Activity purposes.
	 * @param context
	 * @param appWidgetManager
	 * @param appWidgetId
	 */
	public static void updateAppWidget(Context context,
			AppWidgetManager appWidgetManager, int appWidgetId) {
		Log.i(ConnWidget.class.getName(), "Update Appwidget with id "+appWidgetId);

		RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
				R.layout.widget_layout);

		/*
		 * For each button in the list, we add it to the layout, starting at the first button on the left of the widget.
		 * The iterator integer "i" is used to obtained the button id in the layout, and hide the ones not used
		 */
		int i = 0;
		for (ConnButton but : getWidgetsFromPreferences(context, appWidgetId)) {

			//we set the new image of the button in the layout and we make it visible
			remoteViews.setImageViewResource(buttonIds[i], but.getCurrentSelector());

			remoteViews.setViewVisibility(buttonIds[i], View.VISIBLE);

			//Setting the intent to call when clicking the button
			Intent intent = new Intent(context, ConnWidget.class);
			intent.setAction(but.getAction());
			PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
					0, intent, 0);
			remoteViews.setOnClickPendingIntent(buttonIds[i], pendingIntent);
			
			++i;
		}
		
		/*
		 * We hide other ImageButtons
		 * Not sure this is necessary, since the remoteView instance, created in this method,
		 * may not contains the old layout but a new one
		 */
		for (; i < buttonIds.length; ++i) {
			//remoteViews.setViewVisibility(buttonIds[i], View.GONE);
		}

		appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
	}

	@Override
	public void onReceive(Context context, Intent intent) {
        Log.i(this.getClass().getName(), "on receive connWidget action = " + intent.getAction());
        
        super.onReceive(context, intent);
       
        if (intent.getAction().startsWith("fr_imberle")) {
        	
        	Log.d(this.getClass().getName(), "looking for button for action "+intent.getAction());
            ConnButton button = ConnButton.widgetsActions.getGenericButtonFromAction(intent.getAction());
            if (button != null) {

                Log.i(this.getClass().getName(), "switch network! "+button.getClass().getSimpleName());
                button.switchNetwork(context);
            } else {
            	Log.w(this.getClass().getName(), "button not found");
            }
        } else {
        	Log.i(this.getClass().getName(), "action detected is not a custom action : "+intent.getAction());
            
        	ConnBroadcastReceiver br = createWidgetBroadcastReceiver(context, intent.getAction()); //broadcastReceivers.get(intent.getAction());
        	if (br != null) {
        		Log.d(this.getClass().getName(), "broadcast receiver for action "+intent.getAction()+" found");
        		br.onReceive(context, intent);
        	} else {
        		Log.d(this.getClass().getName(), "broadcast receiver NOT found for action "+intent.getAction());
        	}
        }		
	}
	
}
